package com.ticket.websocket;


import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.ticket.api.service.TbUserInfoService;
import com.ticket.api.service.TblMsgContentService;
import com.ticket.api.vo.contentMsg;
import com.ticket.common.string.SimpleJson;
import com.ticket.common.string.StringUtil;
import com.ticket.common.time.CommonFunction;
import com.ticket.db.entity.TblMsgContent;
import com.ticket.db.entity.TblUserInfo;
import com.ticket.io.AppendToFile;
import com.ticket.io.ReadFromFile;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * websocket服务端,多例的，一次websocket连接对应一个实例
 *  @ServerEndpoint 注解的值为URI,映射客户端输入的URL来连接到WebSocket服务器端
 */
@Component
@ServerEndpoint("/{nameId}/{tonameIdId}")  ///websocket/chat
//@ServerEndpoint(value = "/{name}/{toName}",configurator=GetHttpSessionConfigurator.class)
public class WebSocketServer {


    /** 用来记录当前在线连接数。设计成线程安全的。*/
    private static AtomicInteger onlineCount = new AtomicInteger(0);
    /** 用于保存uri对应的连接服务，{uri:WebSocketServer}，设计成线程安全的 */
    private static ConcurrentHashMap<String, WebSocketServer> webSocketServerMAP = new ConcurrentHashMap<>();
    private Session session;// 与某个客户端的连接会话，需要通过它来给客户端发送数据
    private String nameId; //客户端消息发送者
    private String tonameId; //客户端消息接受者
    private String uri; //连接的uri
    private static final String HEADURL="ws://localhost:8080/";
    /**
     * 连接建立成功时触发，绑定参数
     * @param session
     *            可选的参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     * @param nameId
     * @param tonameId
     * @throws IOException
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("nameId") String nameId, @PathParam("tonameIdId") String tonameId) throws IOException {
        this.session = session;
        this.nameId = nameId;
        this.tonameId = tonameId;
        this.uri = session.getRequestURI().toString();
        WebSocketServer webSocketServer = webSocketServerMAP.get(uri);
        System.out.println(nameId+"_"+tonameId);
        if(webSocketServer != null){ //同样业务的连接已经在线，则把原来的挤下线。
         webSocketServer.session.getBasicRemote().sendText(uri + "重复连接被挤下线了");
         webSocketServer.session.close();//关闭连接，触发关闭连接方法onClose()
        }else if(nameId!=null && tonameId!=null){
            String userId1= nameId;String userId2= tonameId;
            String front = StringUtil.Arrays(userId1,userId2);//第一个用户
            String behind = front == userId1?userId2:userId1;//第一个用户
            TblMsgContent content = new TblMsgContent(front,behind);

            TblMsgContentService contentService =  (TblMsgContentService) ApplicationContextRegister.getApplicationContext().getBean(TblMsgContentService.class);
            content = contentService.findTblMsgContentByCondition(content);

            TbUserInfoService userService =  (TbUserInfoService) ApplicationContextRegister.getApplicationContext().getBean(TbUserInfoService.class);
            TblUserInfo userInfo = userService.findTblUserInfoById(tonameId);
            if(userInfo==null){return;}
            String filenameId = "/upload/"+front+'-'+behind+".txt";
           // List<contentMsg> contentMsg= ReadFromFile.readFileByRandomAccess(filenameId,15);
            List<contentMsg> contentMsg= selectHistory(front,behind,15);
//            if(contentMsg==null){
//                AppendToFile.createFile(filenameId);
//            }

                if(content==null){//是否建立连接
                    content = new TblMsgContent();
                String time= CommonFunction.getLocalTime14();
                content.setUserId1(front);
                content.setUserId2(behind);
                content.setStatus(1);
                content.setCreateTime(time);     content.setCreateUser(nameId);
                content.setLastUpdateTime(time); content.setLastUpdateUser(nameId);

                int count=  contentService.insertTblMsgContent(content);
            }

            content.setList(contentMsg);
            content.setUser(userInfo);
        String jsonString = JSON.toJSONString(content);
        sendMessage(jsonString);


       // sendMessage(webSocketServerMAP +"当前在线连接数:" + getOnlineCount());
        }
    webSocketServerMAP.put(uri, this);//保存uri对应的连接服务
        addOnlineCount(); // 在线数加1

    System.out.println(this + "有新连接加入！当前在线连接数：" + getOnlineCount());
    }

    /**
     * 连接关闭时触发，注意不能向客户端发送消息了
     * @throws IOException
     */
    @OnClose
    public void onClose() throws IOException {
        webSocketServerMAP.remove(uri);//删除uri对应的连接服务
        reduceOnlineCount(); // 在线数减1
        System.out.println("有一连接关闭！当前在线连接数" + getOnlineCount());
    }

    /**
     * 收到客户端消息后触发,分别向2个客户端（消息发送者和消息接收者）推送消息
     *
     * @param message
     *            客户端发送过来的消息
     * @param
     * @throws IOException
     */
    @OnMessage
    public void onMessage(String message) throws IOException {
        String userId1= nameId;
        String userId2= tonameId;
        String front = StringUtil.Arrays(userId1,userId2);//第一个用户
        String behind = front == userId1?userId2:userId1;//第二个用户
        System.out.println(message);
        if(message.equals("")){
            List<contentMsg> contentMsg= selectHistory(front,behind,null);
            sendMessage(JSON.toJSONString(contentMsg));
            return;
        }
     String[] arr  = SimpleJson.stringToJson(message,"content","date","address");


        //服务器向消息发送者客户端发送消息
//        this.session.getBasicRemote().sendText("发送给" + toName + "的消息:" + message);
        sendMessage(message);
        //获取消息接收者的客户端连接
        StringBuilder receiverUri = new StringBuilder(HEADURL);
        receiverUri.append(tonameId)
                .append("/")
                .append(nameId);
        WebSocketServer webSocketServer = webSocketServerMAP.get(receiverUri.toString().trim());
     /*   if(webSocketServer != null){*/
                    receiverUri = new StringBuilder(HEADURL);
                    receiverUri.append(nameId)
                            .append("/")
                            .append(tonameId);


            String time= CommonFunction.getLocalTime14();

        TblMsgContent content = new TblMsgContent(front,behind);
            content.setLastUpdateTime(time);
            content.setLastUpdateUser(nameId);

            TblMsgContentService contentService =  (TblMsgContentService) ApplicationContextRegister.getApplicationContext().getBean(TblMsgContentService.class);
            int count = contentService.updateTblMsgContent(content);
            String jsonString = JSON.toJSONString(content);
            String filenameId = "/upload/"+front+'-'+behind+".txt";
            String text="{'content':\""+arr[0]+"\",'date':\""+arr[1]+"\",'msgId':\""+nameId+"\",'address':\""+arr[2]+"\"} \r\n " ;
            AppendToFile.appendMethodB(filenameId,text);
        if (webSocketServer==null){//不在线

        }else {//在线
            webSocketServer = webSocketServerMAP.get(receiverUri.toString().trim());
            webSocketServer.session.getBasicRemote().sendText(jsonString);
        }

            //  String text = "2019/12/09 18:18 , 2 , \"你好!我是测试!\".";
          //  webSocketServer.session.getBasicRemote().sendText("来自" +name + "的消息:" + message);
      /*  }*/
        /*// 群发消息
        Collection<WebSocketServer> collection = webSocketServerMAP.values();
        for (WebSocketServer item : collection) {
            try {
                item.sendMessage("收到群发消息:" + message);
            } catch (IOException e) {
                e.printStackTrace();
                continue;
            }
        }*/
    }

    /**
     * 通信发生错误时触发
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }

    /**
     * 向客户端发送消息
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 获取在线连接数
     * @return
     */
     public static int getOnlineCount() {
        return onlineCount.get();
    }

    /**
     * 原子性操作，在线连接数加一
     */
    public static void addOnlineCount() {
        onlineCount.getAndIncrement();
    }

    /**
     * 原子性操作，在线连接数减一
     */
    public static void reduceOnlineCount() {
        onlineCount.getAndDecrement();
    }

    public static List selectHistory(String front,String behind,Integer count){
        String filenameId = "/upload/"+front+'-'+behind+".txt";
        List<contentMsg> contentMsg= ReadFromFile.readFileByRandomAccess(filenameId,count);
        if(contentMsg==null){
            AppendToFile.createFile(filenameId);
        }
        if(null!=contentMsg){ Collections.reverse(contentMsg);}  //把不是空的list反过来
        return contentMsg;
    }
}